package flathub

import (
	"encoding/json"
	"fmt"
	"os"
	"strings"

	"github.com/godbus/dbus"
	"github.com/godbus/dbus/introspect"
)

const (
	dbusFlatpakHubService   = "com.gitee.zinface.FlatpakHubService"
	dbusFlatpakHubPath      = "/com/gitee/zinface/FlatpakHubService"
	dbusFlatpakHubInterface = "com.gitee.zinface.FlatpakHubService"

	Introspectable = "org.freedesktop.DBus.Introspectable"
)

const intro = `
<node>
    <interface name="com.gitee.zinface.FlatpakHubService">
        <method name="GetAll">
            <arg name="packages" type="s" direction="out" />
        </method>
        <method name="GetAudioVideo">
            <arg name="packages" type="s" direction="out" />
        </method>
        <method name="GetDevelopment">
            <arg name="packages" type="s" direction="out" />
        </method>
        <method name="GetEducation">
            <arg name="packages" type="s" direction="out" />
        </method>
        <method name="GetGame">
            <arg name="packages" type="s" direction="out" />
        </method>
        <method name="GetGraphics">
            <arg name="packages" type="s" direction="out" />
        </method>
        <method name="GetNetwork">
            <arg name="packages" type="s" direction="out" />
        </method>
        <method name="GetOffice">
            <arg name="packages" type="s" direction="out" />
        </method>
        <method name="GetScience">
            <arg name="packages" type="s" direction="out" />
        </method>
        <method name="GetSystem">
            <arg name="packages" type="s" direction="out" />
        </method>
        <method name="GetUtility">
            <arg name="packages" type="s" direction="out" />
        </method>        
    </interface>

    <interface name="org.freedesktop.DBus.Introspectable">
        <method name="Introspect">
            <arg name="xml_data" type="s" direction="out" />
        </method>
    </interface>
</node>
`

type FlatpakManager string
type FlatpakHubService struct{}

var hub *FlatHub

func init() {
	// hub = NewFlatHubPackages()
	// hub = &FlatHub{}
}

func toDBusData(packages Packages) (string, *dbus.Error) {
	data, err := json.Marshal(packages)
	if err != nil {
		return "[]", nil
	} else if strings.Compare(string(data), "null") == 0 {
		return "[]", nil
	}
	return string(data), nil
}

func (m FlatpakHubService) GetAll() (string, *dbus.Error) {
	return toDBusData(hub.All)
}
func (m FlatpakHubService) GetAudioVideo() (string, *dbus.Error) {
	return toDBusData(hub.AudioVideo)
}
func (m FlatpakHubService) GetDevelopment() (string, *dbus.Error) {
	return toDBusData(hub.Development)
}
func (m FlatpakHubService) GetEducation() (string, *dbus.Error) {
	return toDBusData(hub.Education)
}
func (m FlatpakHubService) GetGame() (string, *dbus.Error) {
	return toDBusData(hub.Game)
}
func (m FlatpakHubService) GetGraphics() (string, *dbus.Error) {
	return toDBusData(hub.Graphics)
}
func (m FlatpakHubService) GetNetwork() (string, *dbus.Error) {
	return toDBusData(hub.Network)
}
func (m FlatpakHubService) GetOffice() (string, *dbus.Error) {
	return toDBusData(hub.Office)
}
func (m FlatpakHubService) GetScience() (string, *dbus.Error) {
	return toDBusData(hub.Science)
}
func (m FlatpakHubService) GetSystem() (string, *dbus.Error) {
	return toDBusData(hub.System)
}
func (m FlatpakHubService) GetUtility() (string, *dbus.Error) {
	return toDBusData(hub.Utility)
}

func DBusServiceDaemon() {
	conn, err := dbus.SessionBus()
	if err != nil {
		panic(err)
	}
	defer conn.Close()

	reply, err := conn.RequestName(dbusFlatpakHubService, dbus.NameFlagDoNotQueue)
	if err != nil {
		panic(err)
	}

	if reply == dbus.RequestNameReplyExists {
		fmt.Println("名称已经存在")
		os.Exit(1)
	}
	if reply != dbus.RequestNameReplyPrimaryOwner {
		fmt.Println("名称已经注册")
		os.Exit(1)
	}

	var hub = &FlatpakHubService{}
	conn.Export(hub, dbusFlatpakHubPath, dbusFlatpakHubInterface)
	// conn.Export(flatpakHub, dbusFlatpakHubPath, dbusFlatpakHubInterface)
	conn.Export(introspect.Introspectable(intro), dbusFlatpakHubPath, Introspectable)
	// conn.Export(introspect.Introspectable(intro), "/", Introspectable)

	select {}
}
